package org.itboys.product.service;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.itboys.admin.cache.SysDictionaryLoader;
import org.itboys.admin.entity.SysDictionary;
import org.itboys.admin.service.SysDictionaryService;
import org.itboys.commons.CommonConstants;
import org.itboys.framework.resource.ResourceHolder;
import org.itboys.fuzion.constant.FuzionConstants;
import org.itboys.fuzion.dto.FuzionMemberRedisDto;
import org.itboys.fuzion.entity.FuzionMember;
import org.itboys.fuzion.entity.IncomeExpenditureRecords;
import org.itboys.fuzion.entity.ScoreLevel;
import org.itboys.fuzion.kuaiqian.KQPayInfo;
import org.itboys.fuzion.kuaiqian.KQService;
import org.itboys.fuzion.mysql.dao.FuziongMemberStatisticsMapper;
import org.itboys.fuzion.mysql.orm.FuziongMemberStatistics;
import org.itboys.fuzion.mysql.service.PublicRowService;
import org.itboys.fuzion.service.FuzionMemberService;
import org.itboys.fuzion.service.IncomeExpenditureRecordsService;
import org.itboys.fuzion.service.ScoreLevelService;
import org.itboys.mongodb.core.MongoDataSource;
import org.itboys.mongodb.service.BaseService;
import org.itboys.mongodb.utils.page.Page;
import org.itboys.pay.alipay.AlipayWapResult;
import org.itboys.pay.constant.PayConstants;
import org.itboys.pay.weixin.Unifiedorder;
import org.itboys.pay.weixin.WXPayService;
import org.itboys.pay.weixin.WeixinPaySignTool;
import org.itboys.pay.weixin.WeixinPayUtils;
import org.itboys.product.cache.OrderLoader;
import org.itboys.product.constant.ProductConstant;
import org.itboys.product.entity.Order;
import org.itboys.product.entity.Product;
import org.itboys.redis.RedisCacheClient;
import org.itboys.weixin.entity.WeixinConfig;
import org.itboys.weixin.entity.WeixinSendInfo;
import org.itboys.weixin.service.WeixinConfigService;
import org.itboys.weixin.service.WeixinSendInfoService;
import org.itboys.weixin.tools.WeixinSendUtils;
import org.mongodb.morphia.query.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Maps;

/**
 * Created by huml on 2016/4/19.
 * 订单业务
 */
@Service
public class OrderService extends BaseService<Order, Long> {
    private static final long serialVersionUID = 4495340193729890410L;

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Resource(name="productDS")
    private MongoDataSource orderDS;
    @Resource(name="orderLoader")
    private OrderLoader orderLoader;
    @Resource(name="sysDictionaryLoader")
    private SysDictionaryLoader sysDictionaryLoader;

    @Autowired
    private ProductService productService;
    @Autowired
    private WeixinConfigService weixinConfigService;
    @Autowired
    private ResourceHolder resourceHolder;
    @Autowired
    private FuzionMemberService memberService;
    @Autowired
    private FuziongMemberStatisticsMapper fuziongMemberStatisticsMapper;
    @Autowired
    private IncomeExpenditureRecordsService incomeExpenditureRecordsService;
    @Autowired
    private ScoreLevelService scoreLevelService;
    @Autowired
    private PublicRowService publicRowService;
    @Autowired
    private SysDictionaryService sysDictionaryService;
    @Autowired
    private WeixinSendInfoService sendInfoService;
    @Autowired
    private RedisCacheClient redisCacheClient;

    public static final String FUZION_MEMBER_BUY_BEAN_COUNT = "fuzion_member_buy_bean_count_";//缓存会员购买的能量豆数量

    @Override
    protected MongoDataSource getMongoDataSource() {
        return orderDS;
    }

    @Override
    protected Class<Order> getEntityClass() {
        return Order.class;
    }

    /**
     * 立即购买创建订单
     * @param memberId  购买人id
     * @param productId  产品id
     * @param num  数量
     * @param payMethod  支付方式
     * @param address  地址
     * @param name  订单备注
     * @param mobile 手机号码
     */
    public Order createOrder(Long memberId, Long productId, Integer num,
                            Integer payMethod, String address, String name, String mobile, String postcode){
        Order order = new Order();
        order.setStatus(ProductConstant.OrderStatic.ORDER_STATUS_CREATE);
        order.setMemberId(memberId);
        order.setProductId(productId);
        order.setNum(num);
        order.setPayMethod(payMethod);
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        Product product = productService.getById(productId);
        order.setSellerId(product.getSellerId());
        order.setProductName(product.getName());
        order.setProductImage(product.getImage());
        if(product.getProductStore() == null || product.getProductStore() == 0){
            return null;
        }
        product.setProductStore(product.getProductStore() - num);
        productService.update(product);
        if(payMethod.equals(ProductConstant.OrderStatic.PAY_BEAN)){
            order.setTotalFee(product.getPowerBean() * 100 * num);
        } else {
            order.setTotalFee(product.getPrice() * num);
        }
        order.setMobile(mobile);
        order.setName(name);
        order.setAddress(address);
        order.setPostcode(postcode);
        super.save(order);
        orderLoader.get(order.getOrderNo());//加入redis缓存
        return order;
    }

    /**
     * 购买能量豆
     */
    public Order buyBean(FuzionMember member){
        List<String> list = Lists.newArrayListWithExpectedSize(1);
        list.add(FUZION_MEMBER_BUY_BEAN_COUNT + member.getId());
        Map<String, Long> map = redisCacheClient.get(list, Long.class);
        Long count = map.get(FUZION_MEMBER_BUY_BEAN_COUNT + member.getId());
        if(count == null){
            count = 0L;
        }
        Integer beanCount = sysDictionaryLoader.get(ProductConstant.EnergyBeanProduct.BEAN_COUNT);
        if(count >= beanCount){//购买次数已经达到当日上限
            return null;
        }
        Order order = new Order();
        order.setMemberId(member.getId());
        order.setSellerId(member.getSellerId());
        order.setProductId(ProductConstant.EnergyBeanProduct.BEAN_PRODUCT_ID);
        order.setProductName(ProductConstant.EnergyBeanProduct.BEAN_PRODUCT_NAME);
        order.setStatus(ProductConstant.OrderStatic.ORDER_STATUS_CREATE);
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        int value = sysDictionaryLoader.get(ProductConstant.EnergyBeanProduct.BEAN_PRICE);
        Double price = Double.valueOf(value) * 100;
        order.setTotalFee(price.intValue());
        order.setName(member.getNickname());
        order.setPayMethod(ProductConstant.OrderStatic.PAY_WX);
        order.setNum(FuzionConstants.TYPE_ONE);
        super.save(order);
        orderLoader.get(order.getOrderNo());//加入redis缓存
        return order;
    }

    /**
     * 订单支付
     * @param orderId
     */
    @Transactional
    public Object payOrder(Long orderId, HttpServletRequest request) throws Exception{
        Order order = getById(orderId);
        Integer payMethod = order.getPayMethod();
        FuzionMember member = (FuzionMember)request.getSession().getAttribute("member");
        if(payMethod.equals(ProductConstant.OrderStatic.PAY_BEAN)){
            //   能量豆支付的处理
            IncomeExpenditureRecords records = null;//会员交易记录
            IncomeExpenditureRecords sellRecords = null;//店铺交易记录
            boolean readed = true;
            try {
                FuziongMemberStatistics statistics = fuziongMemberStatisticsMapper.getByMemberId(member.getId());
                if(statistics.getNowEnergyBean() < order.getTotalFee()/100){//能量豆不足
                    return FuzionConstants.TYPE_ZERO;
                }
                if(member.getReaded()){
                    readed = false;
                }
                member.setReaded(true);
                statistics.setNowEnergyBean(statistics.getNowEnergyBean() - order.getTotalFee() / 100);
//            statistics.setBuyCount(statistics.getBuyCount() + 1);
                //判断等级
//            ScoreLevel scoreLevel = scoreLevelService.getByScore(statistics.getBuyCount() + statistics.getEnergyBean());
//            statistics.setScoreId(scoreLevel.getId());
                fuziongMemberStatisticsMapper.update(statistics);//扣除会员能量豆
                //生成会员收支明细表
                records = new IncomeExpenditureRecords();
                records.setMemberId(member.getId());
                records.setType(FuzionConstants.TYPE_ONE);
                records.setMoney(0-order.getTotalFee());
                records.setObjType(FuzionConstants.IncomeExpenditure.SHOPPING_BEAN);
                records.setObjId(String.valueOf(order.getId()));
                incomeExpenditureRecordsService.insert(records);
                // 卖家账户余额变动  如果用能量豆购买,店铺没有收益
//                FuziongMemberStatistics sellerStatistics = fuziongMemberStatisticsMapper.getBySellerId(order.getSellerId());
//                sellerStatistics.setTotalMoney(sellerStatistics.getTotalMoney() + order.getTotalFee());
//                sellerStatistics.setNowTotalMoney(sellerStatistics.getNowTotalMoney() + order.getTotalFee());
//                fuziongMemberStatisticsMapper.update(sellerStatistics);
//                //卖家账户明细记录
//                sellRecords = new IncomeExpenditureRecords();
//                sellRecords.setMemberId(order.getSellerId());
//                sellRecords.setType(FuzionConstants.TYPE_TWO);
//                sellRecords.setMoney(order.getTotalFee());
//                sellRecords.setObjType(FuzionConstants.IncomeExpenditure.SHOPPING_BEAN);
//                sellRecords.setObjId(String.valueOf(order.getId()));
//                incomeExpenditureRecordsService.insert(records);
                //购买商品 处理推荐人收益
//                recIncome(member, productService.getById(order.getProductId()));
                //修改订单状态
                order.setStatus(ProductConstant.OrderStatic.ORDER_STATUS_PAY);
                order.setPayMethod(ProductConstant.OrderStatic.PAY_BEAN);
                order.setPayTime(new Date());
                super.update(order);
                memberService.update(member);
                return order.getId();
            } catch (Exception e) {
                //mongo手动回滚
                if(records != null && records.getId() > 0){
                    incomeExpenditureRecordsService.delete(records.getId());
                }
                if(sellRecords != null && sellRecords.getId() > 0){
                    incomeExpenditureRecordsService.delete(sellRecords.getId());
                }
                if(member != null && readed ){
                    member.setReaded(false);
                    memberService.update(member);
                }
                throw new RuntimeException(e);
            }
        } else if (payMethod.equals(ProductConstant.OrderStatic.PAY_WX)){
            //   微信支付的处理
            String ip = request.getRemoteAddr();
            if(StringUtils.isBlank(ip) || ip.equals("0:0:0:0:0:0:0:1")){
                ip = "112.124.61.23";
            }
            /*WeixinConfig weixinConfig = weixinConfigService.getById(Long.valueOf(member.getWeixinId()));
            WeixinPaySignTool weixinPaySignTool = WeixinPayUtils.paySign(weixinConfig.getAppId(),weixinConfig.getMchId(),member.getOpenId(),order.getOrderNo(),
                    ip,Unifiedorder.TRADE_TYPE_JS,"购买商品",String.valueOf(order.getTotalFee()),
                    resourceHolder.getStringValue("webRoot")+ProductConstant.OrderStatic.WXPAY_NOTIFY_URL,weixinConfig.getMcKkey());*/
            KQPayInfo info = new KQPayInfo(order.getOrderNo(), new BigDecimal(order.getTotalFee()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_DOWN),
                    order.getMemberId(), "能量豆", order.getNum().toString(), resourceHolder.getStringValue("webRoot")+ProductConstant.OrderStatic.WXPAY_NOTIFY_URL + "/" +order.getOrderNo(), "");
            String result = KQService.postAndResult(info);
            logger.info("******************KQService result***************" + result);
            return result;
        }
        return null;
    }

    /**
     * 微信支付异步回调处理
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Transactional
    public String weixinNotify(HttpServletRequest request) throws Exception{
        IncomeExpenditureRecords records = null;//会员交易记录
        IncomeExpenditureRecords sellRecords = null;//店铺交易记录
        FuzionMember member = null;
        boolean readed = true;
        try {
            AlipayWapResult wapResult = WXPayService.notifyResult(request, "1");
            String orderNo = wapResult.getOut_trade_no();
            Order order = getByField("orderNo", orderNo);
            logger.info("**********orderNo**********"+orderNo);
            if(order == null){
                logger.info("****************order == null*************");
                return CommonConstants.FAIL;
            }
            member = memberService.getById(order.getMemberId());
            if(member.getReaded()){
                readed = false;
            }
            member.setReaded(true);
            WeixinConfig weixinConfig = weixinConfigService.getById(Long.valueOf(member.getWeixinId()));
            wapResult = WXPayService.checkIsSuccess(wapResult, weixinConfig.getMcKkey());
            System.out.println(wapResult.toString());
            if (!wapResult.getParams().get(PayConstants.WeixinPay.RESULT_CODE).equals(CommonConstants.SUCCESS.toUpperCase())) {//签名校验失败
                logger.info("****************sign error*************");
                return CommonConstants.FAIL;
            }
            /*if(wapResult.getPrice().compareTo(new BigDecimal(order.getTotalFee())) != 0){//支付金额不正确
                logger.info("****************price error*************");
                return CommonConstants.FAIL;
            }*/
            //修改订单状态并生成支付记录
            //   能量豆支付的处理
            FuziongMemberStatistics statistics = fuziongMemberStatisticsMapper.getByMemberId(member.getId());
//        statistics.setBuyCount(statistics.getBuyCount() + 1);

            if(order.getProductId().equals(ProductConstant.EnergyBeanProduct.BEAN_PRODUCT_ID)){//如果购买的是能量豆,能量豆购买数量加一
                statistics.setEnergyBean(statistics.getEnergyBean() + 1);
                statistics.setNowEnergyBean(statistics.getNowEnergyBean() + 1);
                //判断等级  这里应该是购买的能量豆总数加上推荐的会员数
                long recCount = memberService.countMemberByRecId(member.getRecId());
                ScoreLevel scoreLevel = scoreLevelService.getByScore(statistics.getEnergyBean()+(int)recCount);
                statistics.setScoreId(scoreLevel.getId());
                //公排逻辑
                //publicRowService.buyThanPublicRow(member.getId());
            }
            //购买商品 处理推荐人收益
            recIncome(member, order.getProductId());
            fuziongMemberStatisticsMapper.update(statistics);//扣除能量豆
            //生成收支明细表
            records = new IncomeExpenditureRecords();
            records.setMemberId(member.getId());
            records.setType(FuzionConstants.TYPE_ONE);
            records.setMoney(0 - order.getTotalFee());
            if(order.getProductId().equals(ProductConstant.EnergyBeanProduct.BEAN_PRODUCT_ID)){
                records.setObjType(FuzionConstants.IncomeExpenditure.BEAN_SHOPPING);
            } else {
                records.setObjType(FuzionConstants.IncomeExpenditure.SHOPPING_MONEY);
            }
            records.setObjId(String.valueOf(order.getId()));
            incomeExpenditureRecordsService.insert(records);
            // 卖家账户余额变动
            FuziongMemberStatistics sellerStatistics = fuziongMemberStatisticsMapper.getBySellerId(order.getSellerId());
            sellerStatistics.setTotalMoney(sellerStatistics.getTotalMoney() + order.getTotalFee());
            sellerStatistics.setNowTotalMoney(sellerStatistics.getNowTotalMoney() + order.getTotalFee());
            fuziongMemberStatisticsMapper.update(sellerStatistics);
            //卖家账户明细记录
            sellRecords = new IncomeExpenditureRecords();
            sellRecords.setMemberId(order.getSellerId());
            sellRecords.setType(FuzionConstants.TYPE_TWO);
            sellRecords.setMoney(order.getTotalFee());
            if(order.getProductId().equals(ProductConstant.EnergyBeanProduct.BEAN_PRODUCT_ID)){
                sellRecords.setObjType(FuzionConstants.IncomeExpenditure.BEAN_SHOPPING);
            } else {
                sellRecords.setObjType(FuzionConstants.IncomeExpenditure.SHOPPING_MONEY);
            }
            sellRecords.setObjId(String.valueOf(order.getId()));
            incomeExpenditureRecordsService.insert(sellRecords);
            //修改订单状态
            order.setStatus(ProductConstant.OrderStatic.ORDER_STATUS_PAY);
            order.setPayMethod(ProductConstant.OrderStatic.PAY_WX);
            order.setPayTime(new Date());
            super.update(order);
            if(order.getProductId().equals(ProductConstant.EnergyBeanProduct.BEAN_PRODUCT_ID)){//如果购买的是能量豆,要加入公排逻辑
                //公排逻辑
                publicRowService.buyThanPublicRow(member.getId());
            }
            logger.info("****************success*************");
            return CommonConstants.SUCCESS;
        } catch (Exception e) {
            //mongo手动回滚
            if(records != null && records.getId() > 0){
                incomeExpenditureRecordsService.delete(records.getId());
            }
            if(sellRecords != null && sellRecords.getId() > 0){
                incomeExpenditureRecordsService.delete(sellRecords.getId());
            }
            if(member != null && readed ){
                member.setReaded(false);
                memberService.update(member);
            }
            throw new RuntimeException(e);
        }
    }

    /**
     * 会员购买产品时,推荐人的收益
     * @param member
     * @param productId
     */
    public void recIncome(FuzionMember member, Long productId){
        Long recId = member.getRecId();
        int income = 0;
        if(productId == 0){//能量豆
            int value = sysDictionaryLoader.get(ProductConstant.EnergyBeanProduct.BEAN_SCALE);
            income = Integer.valueOf(value) * 100;
        } else {//其他商品
            Product product = productService.getById(productId);
            int scale1 = product.getScale();//提成比例
            int price = product.getPrice();//商品售价
            BigDecimal scale = new BigDecimal(scale1).multiply(new BigDecimal(price)).divide(new BigDecimal(100));
            income = scale.intValue();
        }
        if(recId != null && income > 0){
            FuziongMemberStatistics recMemberStatistics = fuziongMemberStatisticsMapper.getByMemberId(recId);
            if(recMemberStatistics != null){
                FuziongMemberStatistics recMemberTemp = new FuziongMemberStatistics();
                recMemberTemp.setId(recMemberStatistics.getId());
                recMemberTemp.setMemberId(recMemberStatistics.getMemberId());
                logger.info("***********income************"+income);
                //更改账户余额值
                //recMemberStatistics.setNowTotalMoney(recMemberStatistics.getNowTotalMoney() + income);
                recMemberTemp.setTotalMoney(income);
                recMemberTemp.setDynamicIncome(income);//直销  是动态收益
                recMemberTemp.setNowTotalMoney(income);//积分
                //fuziongMemberStatisticsMapper.update(recMemberStatistics);
                fuziongMemberStatisticsMapper.updateStatistics(recMemberTemp);
                //生成记录
                IncomeExpenditureRecords records = new IncomeExpenditureRecords();
                records.setMemberId(recId);
                records.setMoney(income);
                records.setObjType(FuzionConstants.IncomeExpenditure.DISTRIBUTION_MONEY);
                records.setObjId(member.getId()+"");
                incomeExpenditureRecordsService.insert(records);

                FuzionMember recMember = memberService.getById(recId);
                WeixinConfig weixinConfig = weixinConfigService.getById(Long.valueOf(recMember.getWeixinId()));
                WeixinSendInfo sendInfo = sendInfoService.getByKey("energy_bean_scale");
                Double income1 = new BigDecimal(income).divide(new BigDecimal(100)).doubleValue();
                WeixinSendUtils.sendMessage(weixinConfig.getAppId(), weixinConfig.getAppSecret(), recMember.getOpenId(),
                        sendInfo.getValue().replace("{memberName}",member.getNickname()).replace("{scale}", income1+""));
                
                
            }
            
            //根据推荐的人数  设置推荐人会员等级
			/*String recscoreName = null;
			FuziongMemberStatistics recfms = fuziongMemberStatisticsMapper.getByMemberId(member.getRecId());
			if(recfms != null){
				Long recCount = memberService.countMemberByRecId2(member.getRecId());//已经推荐的会员数量
				if(member.getReaded()){
					recCount = recCount + 1;
				}
				if(recCount >0 && recCount < 3){//推荐人
					if(recfms.getScoreId() < 1L){
						recfms.setScoreId(1L);
						recscoreName = "青铜";
					}
				}else if(3 <= recCount && recCount < 9){
					if(recfms.getScoreId()<2L){
						recfms.setScoreId(2L);
						recscoreName = "白金";
					}
				}else if(recCount >= 9){
					if(recfms.getScoreId()<3L){
						recfms.setScoreId(3L);
						recscoreName = "王者";
					}
				}
				

				//修改推荐人会员等级 并告知会员等级提升了
				if(StringUtils.isNotBlank(recscoreName)){
					fuziongMemberStatisticsMapper.updateByMemberId(recfms);
					
					FuzionMemberRedisDto redis_fuzion_member = memberService.getFuzionMemberRedisDto(member.getRecId());
					WeixinSendInfo wsss = sendInfoService.getByKey("score_level_to_up");
					String messagess = wsss.getValue().replace("{scoreName}", recscoreName);
					WeixinSendUtils.sendMessage(redis_fuzion_member.getAppId(), redis_fuzion_member.getAppSecret(),
							redis_fuzion_member.getOpenId(), messagess);
				}
			}*/
        }
    }
    
    /**
     * 订单首页
     * @param rows
     * @param status
     * @return
     */
    public List<Order> myOrderFirstPage(Integer rows, Integer status, Long memberId){
        Query<Order> query = getMongoDataSource().createQuery(getEntityClass()).filter("isDeleted",0).filter("memberId", memberId);
        if(status != null){
            if(status == 0){
                query = query.filter("status", status);
            } else {
                query = query.filter("status >", 0);
            }
        }
        query.order("-createTime").offset(0).limit(rows);
        return query.asList();
    }

    /**
     * 分页获取订单
     * @param memberId
     * @param status
     * @param request
     * @return
     */
    public List<Order> myOrder(Long memberId, Integer status, HttpServletRequest request){
        Map<String, Object> param = Maps.newHashMapWithExpectedSize(2);
        param.put("memberId", memberId);
        param.put("isDeleted", 0);
        if(status != null){
            if(status == 0){
                param.put("status", status);
            }else {
                param.put("status >", 0);
            }
        }
        Page<Order> page = pageQuery(param, request);
        return page.getData();
    }
    
}
